<template>
  <div class="upload">
    <!-- draggable是拖拽组件 -->
    <draggable
      v-if="selectedItems.length"
      v-model="selectedItems"
      @start="drag = true"
      @end="drag = false"
      @update="onUpdate"
    >
      <transition-group
        class="draggable-item"
        type="transition"
        :name="'flip-list'"
      >
        <div
          v-loading="loading"
          v-for="(item, index) in selectedItems"
          :key="item.url ? item.url : `image_url${index}`"
          class="file-item"
          :style="`width: ${width * 4}px; height: 60px;`"
        >
          <audio
            id="audio"
            controls
            style="width: 100%; height: 100%;"
            :src="item.url"
          />
          <i class="el-icon-error" @click="handleDeleteFileItem(index)"></i>
        </div>

        <div class="music-name" key="music-name">
          上传文件名称：{{ musicName || fileName }}
        </div>
      </transition-group>
    </draggable>

    <div v-show="!selectedItems.length" class="upload-image">
      <el-upload
        ref="upload"
        name="iFile"
        list-type="picture-card"
        action="#"
        :disabled="loading"
        :limit="limit"
        :auto-upload="autoUpload"
        :multiple="limit > 1"
        :accept="accept"
        :before-upload="beforeUpload"
        :http-request="onUpload"
        :on-change="handUploadChange"
      >
        <div slot="trigger" title="点击选择音乐" class="btn-select-music">
          <el-button type="plain">点击选择音乐</el-button>
        </div>
      </el-upload>
    </div>
  </div>
</template>

<script>
import OSS from 'ali-oss'
import draggable from 'vuedraggable'
import { debounce } from '@/utils/util'
import cloneDeep from 'lodash.clonedeep'

// 上传配置
const client = new OSS({
  accessKeyId: 'LTAI5t7WmZr8KZceY8Zo9NjE', // 查看你自己的阿里云KEY
  accessKeySecret: 'MpSEdooPM2V87wer9IecXR5PI4K80P', // 查看自己的阿里云KEYSECRET
  bucket: 'chaosageservice', // 你的 OSS bucket 名称
  region: 'oss-cn-guangzhou',
  cname: true, // 开启自定义域名上传
  endpoint: 'oss.chaosageservice.com', // 自己的域名
})

// 选择视频组件，目前只支持单选
export default {
  name: 'SelectVideo',
  components: {
    draggable,
  },
  props: {
    // 限制文件上传个数
    limit: {
      type: Number,
      default: 1,
    },
    // 默认显示的文件
    defaultList: {
      type: Array,
      default: () => [],
    },
    // 元素的尺寸(宽)
    width: {
      type: Number,
      default: 80,
    },
    // 是否为自动上传
    autoUpload: {
      type: Boolean,
      default: true,
    },
    // 上传音乐文件名
    fileName: String,
    // 音乐上传完成
    completed: {
      type: Boolean,
      default: false,
    },
  },
  model: {
    prop: 'value',
    event: 'change',
  },
  data() {
    return {
      // 加载
      loading: false,
      // 是否可见
      visible: false,
      // 允许上传的文件类型
      accept: '.mp3',
      // 上传文件大小限制
      uploadSizeLimit: 10,

      // 选择的图片列表
      selectedItems: [],
      // 禁止传参 (防止重新赋值)
      allowProps: true,
      // 上传成功的音乐url
      musicUrl: undefined,
      // 上传的音乐名称
      musicName: '',
    }
  },
  watch: {
    // 设置默认数据
    defaultList: {
      immediate: true,
      handler(val) {
        // 避免重复赋值
        if (this.allowProps) {
          this.selectedItems = cloneDeep(val)
          this.onChange()
        }
      },
    },
  },
  computed: {
    uploaded: {
      get() {
        return this.completed
      },
      set(val) {
        this.$emit('update:completed', val)
      },
    },
  },
  methods: {
    onUpdate() {
      this.onChange()
    },

    // 视频上传之前触发(一般此处做文件上传大小限制)
    beforeUpload(file) {
      console.log('音乐上传之前触发==>', file)
      // 验证上传的文件大小
      const fileSizeMb = file.size / 1024 / 1024
      // 上传大小限制30M
      if (fileSizeMb > this.uploadSizeLimit) {
        this.$message.error(`上传的音乐文件大小不能超出${this.uploadSizeLimit}MB`)
        return false
      }
      return true
    },

    // 手动上传文件，调用此方法将执行上传文件操作
    upload() {
      this.$refs.upload.submit()
    },

    // 自定义上传
    async onUpload(options) {
      console.log('自定义上传==>', options)
      try {
        // // 拿到上传的文件
        const file = options.file
        // 创建日期实例
        let now = new Date()
        // 设置路径
        const path = `swissabl${now.getFullYear()}/${
          now.getMonth() + 1
        }/${now.getTime()}_${file.name}`
        this.musicName = file.name
        // 开始上传
        const res = await this.handleUpload(path, file)
        if (res.url) {
          this.uploaded = true
          this.musicUrl = res.url
          // 更新组件v-model绑定值
          this.onChange()
        }
      } catch (e) {
        this.uploaded = false
        this.loading = false
        console.log('上传视频文件失败==>', e)
        this.onChange()
        this.$message.error('上传失败，请重试！')
      }
    },

    // 开始上传
    handleUpload(path, file) {
      const that = this
      // 开始加载
      that.loading = true
      return new Promise((resolve, reject) => {
        client
          .put(path, file)
          .then((result) => {
            if (result.res.statusCode !== 200) {
              console.log('音乐上传失败到阿里云==>', result)
              throw new Error(result.res.Message)
            }
            resolve(result)
            console.log('音乐上传成功到阿里云==>', result)
          })
          .catch((err) => {
            reject(err)
            console.log('上传失败', err)
          })
          .finally(() => {
            that.loading = false
          })
      })
    },

    // 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
    handUploadChange(file, fileList) {
      console.log('文件状态改变时的钩子==>', fileList)

      // 显示错误提示(防抖处理)
      const showErrorMsg = debounce(this.$message.error, 20)
      // 如为多选，此处还需设置最大选择数量
      if (this.limit > 1 && this.limit <= 5) {
        showErrorMsg(`一次上传的文件数量不能超出${this.limit}个`)
        return false
      }
      this.selectedItems = fileList
      // 更新父组件绑定值
      this.onChange()
    },

    // 删除选中文件
    handleDeleteFileItem(index) {
      this.selectedItems.splice(index, 1)
      if (this.selectedItems.length === 0) {
        this.allowProps = false
      }
      this.onChange()
    },

    // 触发change事件
    onChange() {
      if (this.selectedItems.length <= 0) {
        return this.$emit('change', '')
      }
      if (this.musicUrl) {
        return this.$emit('change', this.musicUrl)
      }
    },

    // 清空
    clearSelectItem() {
      // 清空选择
      this.selectedItems.length ? this.selectedItems.splice(0) : ''
      // 重置默认值,允许传参
      this.allowProps = true
      // 清空已上传的文件列表（该方法不支持在 before-upload 中调用）
      this.$refs.upload.clearFiles()
      // 更新父组件绑定值
      this.onChange()
    },
  },
}
</script>

<style lang="scss" scoped>
.btn-select-music::v-deep {
  line-height: 0;
}

// 文件元素
.file-item {
  position: relative;
  // float: left;
  width: 80px;
  height: 80px;
  position: relative;
  padding: 2px;
  .img-cover {
    display: block;
    // width: 100%;
    height: 100%;
    background: no-repeat center center / 100%;
  }
  &:hover {
    .el-icon-error {
      display: block;
    }
  }
  .el-icon-error {
    display: none;
    position: absolute;
    top: -3px;
    right: -3px;
    cursor: pointer;
    font-size: 16px;
    z-index: 2001;
    color: #c5c5c5;
    &:hover {
      color: #7d7d7d;
    }
  }
  &:hover {
    border: 1px solid #a7c3de;
    border-radius: 50px;
  }
}

.file-item::v-deep {
  .el-loading-mask {
    border-radius: 50000px;
  }
}

.music-name {
  font-size: 15px;
  color: #409eff;
}

// 上传图片样式
.upload-image::v-deep {
  .el-upload--picture-card {
    width: auto;
    height: auto;
    background-color: rgba(239, 240, 245);
    border: none;
  }
  // 隐藏picture-card图片列表
  .el-upload-list--picture-card {
    display: none;
  }
}
</style>
